package songhq.crypto;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.sql.SQLOutput;
import java.util.Base64;
import java.util.Calendar;
import java.util.HashMap;

/**
 * RAS 算法
 */
public class RsaUtil {

    /**
     * 生成公私钥匙
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static HashMap<String,String> generateKeyPair() throws NoSuchAlgorithmException {

        HashMap<String, String> keyPairMap = new HashMap<>();
        KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
        rsa.initialize(2048,new SecureRandom());
        KeyPair keyPair = rsa.generateKeyPair();
        PrivateKey aPrivate = keyPair.getPrivate();
        byte[] encoded = aPrivate.getEncoded();
        String privateKey = Base64.getEncoder().encodeToString(encoded);
        PublicKey aPublic = keyPair.getPublic();
        String publicKey = Base64.getEncoder().encodeToString(aPublic.getEncoded());
        keyPairMap.put("privateKey",privateKey);
        keyPairMap.put("publicKey",publicKey);
        return keyPairMap;
    }

    /**
     * 加密
     * @param str
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String str,String publicKey) throws Exception {
        byte[] decoded = Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decoded);
        PublicKey rsa = getPublicKey(publicKey);
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE,rsa);
        byte[] bytes = cipher.doFinal(str.getBytes("UTF-8"));
        String secretText  = Base64.getEncoder().encodeToString(bytes);
        return secretText;
    }

    /**
     * 解密
     * @param str
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static  String decryptByPrivateKey(String str,String privateKey) throws Exception{
        byte[] decode = Base64.getDecoder().decode(str);
        PrivateKey rsa = getPrivateKey(privateKey);
        Cipher rsa1 = Cipher.getInstance("RSA");
        rsa1.init(Cipher.DECRYPT_MODE,rsa);
        byte[] bytes = rsa1.doFinal(decode);
        return new String(bytes);

    }

    /**
     * 从base64 String 格式的转成PrivateKey对象
     * @param privateKey
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey){
        try{

            byte[] byteKey = Base64.getDecoder().decode(privateKey);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
            KeyFactory rsa = KeyFactory.getInstance("RSA");
            PrivateKey key = rsa.generatePrivate(pkcs8EncodedKeySpec);
            return key;
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        return null;
    }
    public static PublicKey getPublicKey(String publicKey){
        try{

            byte[] byteKey = Base64.getDecoder().decode(publicKey);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
            KeyFactory rsa = KeyFactory.getInstance("RSA");
            return rsa.generatePublic(x509EncodedKeySpec);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        return null;
    }


    /**
     * 用私钥对明文进行签名
     * @param privateKey
     * @param dataStr
     * @return
     */
    public static String sign(String privateKey,String dataStr){

        PrivateKey privateKey1 = getPrivateKey(privateKey);
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(privateKey1);
            sign.update(dataStr.getBytes());
            byte[] sign1 = sign.sign();
            String s = Base64.getEncoder().encodeToString(sign1);
            return s;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 用公钥 对明文和签名进行验证
     * @param publicKey
     * @param dataStr
     * @param signature
     * @return
     */
    public static boolean verifySign(String publicKey, String dataStr, String signature){
        PublicKey publicKey1 = getPublicKey(publicKey);
        try{

            Signature verifySign = Signature.getInstance("SHA256withRSA");
            verifySign.initVerify(publicKey1);
            verifySign.update(dataStr.getBytes());
            boolean verify = verifySign.verify(Base64.getDecoder().decode(signature));
            return verify;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }







    public static void main(String[] args) throws Exception {
        HashMap<String, String> kerPair = generateKeyPair();
        String pureText = "hello world";
        System.out.println(pureText);
        //String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmBkGnveu14XGloVS1SvvxeuLposwKFcrpqhd0EeO8nSVXkozoIlo4/bxsHAs8Tc8EuOSYpMd4R/99H9JE+DMk7JaGAIoqJVnBhNmltTGGoiXaurpcYOLYDXMNP11NHVcZiR5LHDqjemAbCVXN54kFlLwvZT7UI9IVXkMjE3LTGsjhR5hBiqxlj2pi8XySrYRcOYj/5MedtDNHiclXit25lfP87pERVlMNyEuPRwkUgRK3rrLOryXVyuiQ2i/AS76g9zDfFdq8Aed1/2yTCyCZD7T3szriWuXSR7/nKKEIgDOSghGP3YopQE9GSgepsu0yII8Hv4q5dy1lXy7M6WNAwIDAQAB";
        String publicKey = kerPair.get("publicKey");
        //String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCYGQae967XhcaWhVLVK+/F64umizAoVyumqF3QR47ydJVeSjOgiWjj9vGwcCzxNzwS45Jikx3hH/30f0kT4MyTsloYAiiolWcGE2aW1MYaiJdq6ulxg4tgNcw0/XU0dVxmJHkscOqN6YBsJVc3niQWUvC9lPtQj0hVeQyMTctMayOFHmEGKrGWPamLxfJKthFw5iP/kx520M0eJyVeK3bmV8/zukRFWUw3IS49HCRSBEreuss6vJdXK6JDaL8BLvqD3MN8V2rwB53X/bJMLIJkPtPezOuJa5dJHv+cooQiAM5KCEY/diilAT0ZKB6my7TIgjwe/irl3LWVfLszpY0DAgMBAAECggEAKsnXj/80A9PRo2TMgcYDhVWXivnbSW4EjLUO91o6P8FGiCktzvr5NDCzm6RjMFUOpG27L9odbMj4Q8FPSLVUODTTna91yr+FJTNuB/7B4JMOrfh6RgHwwtc/pKStRV3C6cVXBYaapePLyiDTIYVut40LxvnTnb1BZzJPsmTsTYngF6UvR4INQssczqcV+YSWQyfi2mMsODvsA6hJbG8qCVtpI7/V/5nwm0XXkeGB3/c73J/rENiiPsSiLjRbebz5CoqWuSlTwXpF6eCnrc5epSSbofBxnUt5BJ1UGE1PIBrx5CStTmulOeFfV80UpamLZcwJgKf0etr2ZxwjC1mx6QKBgQD80IJJydXcjCXjOoj0g1tbUI+Mj9ysqSk7BZkCJM3QcSWhuSiQxhdk3l0v4MKzdfoZbSmHVsAiIntgU1Urgsy1rGWmzTzy9FtYzdjMjQLcpZt1Sxdxl/egw6zYB47XFsUCL4z1DNdUihf6gcsYs8qyc7K3i8qOH3Bi1d6vkkuYXwKBgQCaA6PW9zh0RrI9ArgoVAfVjUrxGkqBzqb/eZD/LqNqmw32FsmbLZ0gRdV9tH22UfqBXkxGOf6qD5bSG/lIPCjUSB7TptdOuB8UkIfEA2vYbqDqNknqHF7lGB+gH8wpYSA/zpPmx+LbTeAJjHxFvbXOc6S4Qnsli9JgE8SBTMfd3QKBgGzQkkOQTCyRZf1XxHr5zuiO1Dp78U+fv89XqXPyw2NkT/474+nsWUVhMFrbMvJrZSpsgeNuw2Pt04yyUYZY1iOcAGS7EfDAnFCsyRPB3el6nl7t4zlRX5QipNKW7jRF6KX4MYOH82a/yXJZS0FmoWgNxG6cDKL/hTAFPcP0A/WhAoGAF7M5sinG+TWr1fGmLyaHMhiVELcQAhuv3R5y7qHZqd0Eb/sfuQ5y4HV+neJ5eeXxm5jMOf5QrxDJD7oYSUJgshILFFzXQxjYR4zaJ5KzNNIJVyFVjH4jKDPnIffirfdxRABhCCF4SnEYab/Bm+XOpV9sWKJ6WtPCYuCH27HaC80CgYEAn11kjx6Eu12mLh1uXh/WvtfQU+iFUDy2zCX+t7r83wSM8vefgHD5YgvqpB0MGO+48YpKIl4A87AFzNJ6nCd7L4Ej0Cp29XSXkToDx9W1c0bs+wDmCsahyRia1nGWBqaF+GM/md9TIPs7eBvyIhmPCIvWNMqN0OoEWRu7S+YZt4M=";
        String privateKey = kerPair.get("privateKey");
        System.out.println("私钥"+ privateKey);
        System.out.println("公钥" +publicKey );
        String cryptText = encryptByPublicKey(pureText, publicKey);
        String s = decryptByPrivateKey(cryptText, privateKey);
        String sign = sign(privateKey, pureText);
        boolean b = verifySign(publicKey, pureText, sign);
        System.out.println(s);
        System.out.println("验签结果为：" + b);

    }




}
